import copy
import datetime
import json
import time as _time
import uuid
import os

import requests
from loguru import logger

from config import config
from push.urls import PushUrl


class PushClient:

    def __init__(self, timeout=3):
        self.http_header = {"Content-Type": "application/json; charset=utf-8"}
        self.config = config.Config()
        self.timeout = timeout
        self.card_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "card")
        self.buy_card_file = os.path.join(self.card_dir, "buy_card.json")
        self.sell_card_file = os.path.join(self.card_dir, "sell_card.json")
        with open(self.buy_card_file, 'r') as bf:
            self.buy_card = json.loads(bf.read())
        with open(self.sell_card_file, 'r') as sf:
            self.sell_card = json.loads(sf.read())

    # 获取发送消息请求头
    def send_message_header(self) -> dict:
        tenant_access_token = self.get_tenant_access_token()
        message_header = {"Authorization": "Bearer {}".format(tenant_access_token), "Content-Type": "application/json"}
        print(message_header)
        return message_header

    # 获取发送消息请求体
    def send_message_body(self, content, msg_type="text") -> dict:
        content_uuid = str(uuid.uuid4())
        receive_id = self.config.read_config()["push"]["chatid"]
        message_body = {"receive_id": receive_id, "msg_type": msg_type, "content": content, "uuid": content_uuid}
        # print(message_body)
        return message_body

    # 生成推送消息内容
    @staticmethod
    def send_message_content(detail_dict) -> str:
        action_type = detail_dict["action_type"]
        stock_code = detail_dict["stock_code"]
        stock_name = detail_dict["stock_name"]
        price = detail_dict["price"]
        push_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        if action_type == "买入":
            fenbi_data = detail_dict["fenbi_data"]
            cost_slippage = detail_dict["cost_slippage"]
            buy_cost = price + cost_slippage
            stop_point = detail_dict["stop_point"]
            buy_time = detail_dict["buy_time"]
            text_content = "🚒{} \n股票代码：{} \n股票名称：{} \n买入价格：{:.2f} \n成本滑点：{:.2f} \n买入成本：{:.2f} \n止损点：{:.2f} \n买入时间：{} \n推送时间：{}".format(action_type, stock_code, stock_name, price, cost_slippage, buy_cost, stop_point, buy_time, push_time)
            # send_content = json.dumps({"text": text_content})
        else:
            stage = detail_dict["stage"] * 100
            sell_type = detail_dict["sell_type"]
            sell_time = detail_dict["sell_time"]
            profile_ratio = detail_dict["profile_ratio"]
            text_content = "🚑{} \n股票代码：{} \n股票名称：{} \n卖出价格：{:.2f} \n卖出仓位：{}% \n预计收益：{:.2%} \n卖出原因：{} \n卖出时间：{} \n推送时间：{}".format(action_type, stock_code, stock_name, price, stage, profile_ratio, sell_type, sell_time, push_time)
        send_content = json.dumps({"text": text_content})
        return send_content

    def send_template_message_content(self, detail_dict) -> str:
        action_type = detail_dict["action_type"]
        stock_code = detail_dict["stock_code"]
        stock_code_normal = stock_code.split('.')[0]
        stock_name = detail_dict["stock_name"]
        price = detail_dict["price"]
        trade_account = detail_dict["trade_account"]
        trade_qty = detail_dict["trade_qty"]
        is_autotrade = str(detail_dict["is_autotrade"])
        push_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        if action_type == "买入":
            send_card = copy.deepcopy(self.buy_card)
            trade_url = "{}/buy/{}/{}/{}/{}".format(self.config.read_config()["autotrading"]["url"], trade_account, stock_code_normal, "{:.2f}".format(price), trade_qty)
            cost_slippage = detail_dict["cost_slippage"]
            buy_cost = price + cost_slippage
            stop_point = detail_dict["stop_point"]
            buy_time = detail_dict["buy_time"]
            send_card['data']['template_variable']["stock_code"] = stock_code
            send_card['data']['template_variable']["stock_name"] = stock_name
            send_card['data']['template_variable']["buy_price"] = '<font color=\'red\'>' + "{:.2f}".format(price) + '</font>'
            send_card['data']['template_variable']["cost_slippage"] = "{:.2f}".format(cost_slippage)
            send_card['data']['template_variable']["buy_cost"] = "{:.2f}".format(buy_cost)
            send_card['data']['template_variable']["stop_point"] = "{:.2f}".format(stop_point)
            send_card['data']['template_variable']["buy_time"] = buy_time
            send_card['data']['template_variable']["push_time"] = push_time
            send_card['data']['template_variable']["trade_account"] = "{}".format(trade_account)
            send_card['data']['template_variable']["trade_qty"] = "{}".format(trade_qty)
            send_card['data']['template_variable']["is_autotrade"] = is_autotrade
            send_card['data']['template_variable']["trade_url"] = trade_url

            # send_content = json.dumps(send_buy_card)
        else:
            send_card = copy.deepcopy(self.sell_card)
            stage = detail_dict["stage"]
            sell_type = detail_dict["sell_type"]
            sell_time = detail_dict["sell_time"]
            trade_url = "{}/sell/{}/{}/{}/{}".format(self.config.read_config()["autotrading"]["url"], trade_account, stock_code_normal, "{:.2f}".format(price), trade_qty)
            profile_ratio = float(detail_dict["profile_ratio"])
            profile_ratio_percent = "{:.2%}".format(detail_dict["profile_ratio"])
            cost_slippage = detail_dict["cost_slippage"]
            buy_time = detail_dict["buy_time"]
            buy_price = detail_dict["buy_price"]
            buy_cost = buy_price + cost_slippage
            price_diff = (price - buy_cost) * 100
            expect_income = (price - buy_cost) * float(trade_qty)
            # 基本信息
            send_card['data']['template_variable']["stock_code"] = stock_code
            send_card['data']['template_variable']["stock_name"] = stock_name
            # 买入信息
            send_card['data']['template_variable']["buy_price"] = "{:.2f}".format(buy_price)
            send_card['data']['template_variable']["buy_time"] = buy_time
            send_card['data']['template_variable']["cost_slippage"] = "{:.2f}".format(cost_slippage)
            send_card['data']['template_variable']["buy_cost"] = "{:.2f}".format(buy_cost)
            # 卖出信息
            send_card['data']['template_variable']["sell_price"] = "{:.2f}".format(price)
            send_card['data']['template_variable']["sell_stage"] = "{:.2%}".format(stage)
            if profile_ratio > 0:
                send_card['data']['template_variable']["profile_ratio"] = f'<font color=\'red\'> {profile_ratio_percent} </font>'
            elif profile_ratio < 0:
                send_card['data']['template_variable']["profile_ratio"] = f'<font color=\'green\'> {profile_ratio_percent} </font>'
            elif profile_ratio == 0:
                send_card['data']['template_variable']["profile_ratio"] = profile_ratio_percent
            send_card['data']['template_variable']["price_diff"] = "{:.0f}".format(price_diff)
            send_card['data']['template_variable']["expect_income"] = "{:.2f}".format(expect_income)
            send_card['data']['template_variable']["sell_type"] = sell_type
            send_card['data']['template_variable']["sell_time"] = sell_time
            send_card['data']['template_variable']["push_time"] = push_time
            send_card['data']['template_variable']["trade_account"] = "{}".format(trade_account)
            send_card['data']['template_variable']["trade_qty"] = "{}".format(trade_qty)
            send_card['data']['template_variable']["is_autotrade"] = is_autotrade
            send_card['data']['template_variable']["trade_url"] = trade_url
        send_content = json.dumps(send_card)
        return send_content

    def request_send_message(self, request_header, request_body):
        if self.config.read_config()["push"]["open"] == 0:
            return
        self.request_url(PushUrl.SEND_MESSAGE_URL, request_header, request_body)

    # 获取tenant_access_token
    def get_tenant_access_token(self) -> str:
        config_content = self.config.read_config()
        token_timestamp = config_content["push"]["tokentime"]
        # print(float(datetime.datetime.now().timestamp()) - token_timestamp)
        # print(config_content["push"]["expire"] - 600)
        if float(datetime.datetime.now().timestamp()) - token_timestamp < config_content["push"]["expire"] - 600:
            logger.info("Token from cache {}".format(float(datetime.datetime.now().timestamp()) - token_timestamp))
            return config_content["push"]["token"]
        else:
            appid = self.config.read_config()["push"]["appid"]
            appsecret = self.config.read_config()["push"]["appsecret"]
            payload = json.dumps({
                "app_id": appid,
                "app_secret": appsecret
            })
            headers = {
                'Content-Type': 'application/json'
            }
            response = requests.request("POST", PushUrl.TENANT_ACCESS_TOKEN_URL, headers=headers, data=payload)
            token_dict = json.loads(response.text)
            # print(token_dict)
            if token_dict["code"] == 0:
                config_content = self.config.read_config()
                config_content["push"]["token"] = token_dict["tenant_access_token"]
                config_content["push"]["tokentime"] = datetime.datetime.now().timestamp()
                config_content["push"]["expire"] = token_dict["expire"]
                self.config.write_config(config_content)
                return token_dict["tenant_access_token"]
            else:
                logger.error(response.text)
                return ""

    # 设置请求超时时间
    def set_request_time_out(self, timeout):
        self.timeout = timeout

    # 请求url
    def request_url(self, url, header, payload):
        logger.debug("request url: {}, request data: {}".format(url, payload))
        while True:
            try:
                push_response = requests.post(url=url, headers=header, data=json.dumps(payload), timeout=self.timeout)
                break
            except requests.RequestException as e:
                logger.error("request error: {}".format(e))
                _time.sleep(0.5)

        # print(ths_response.text)
        ths_result = json.loads(push_response.content)
        logger.info(push_response)
        logger.info(ths_result)
        return ths_result


# 测试代码
if __name__ == "__main__":
    push_client = PushClient()
    # message_detail = {"stock_code": self.stock_code,
    #                   "stock_name": self.stock_info.stock_name,
    #                   "price": self.stock_info.buy_price,
    #                   "action_type": "买入",
    #                   "fenbi_data": fenbi_data,
    #                   "stop_point": self.stock_info.stop_point,
    #                   "cost_slippage": cost_slippage
    #                   }
    # message_detail = {"stock_code": self.stock_code,
    #                   "stock_name": self.stock_info.stock_name,
    #                   "buy_price": self.stock_info.buy_price,
    #                   "cost_slippage": cost_slippage,
    #                   "buy_cost_price": self.stock_info.buy_cost,
    #                   "buy_time": self.stock_info.buy_time,
    #                   "price": price,
    #                   "action_type": "卖出",
    #                   "profile_ratio": profile_ratio,
    #                   "stage": stage,
    #                   "sell_type": sell_type,
    #                   "sell_time": self.stock_info.latest_fenbi_data.loc[0, "time"],
    #                   }
    send_content = push_client.send_message_content(message_detail)
    # print(send_content)
    # print(pushApi.get_tenant_access_token())
    send_header = push_client.send_message_header()
    send_body = push_client.send_message_body(send_content)
    push_client.request_send_message(send_header, send_body)